#! /usr/bin/env python3
# encoding: utf-8
"""
@file: views.py
@author: www.xcooo.cn
@Mail: 602006050@qq.com
"""
from flask import abort
from flask import current_app
from flask import g, jsonify
from flask import redirect
from flask import render_template
from flask import request
from flask import session

from info import constants
from info import db
from info.models import Category, News, User
from info.utils.captcha.image_storage import storage
from info.utils.common import user_login_data
from info.utils.response_code import RET
from . import profile_blu

@profile_blu.route('/other_news_list')
def other_news_list():
    '''
    返回指定用户发布的新闻
    :return:
    '''
    # 1. 获取参数'
    other_id = request.args.get('user_id')
    page = request.args.get('p',1)

    # 2. 校验参数
    if not ([other_id,page]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据查询错误')

    try:
        other = User.query.get(other_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据查询错误')

    if not other:
        return jsonify(errno=RET.NODATA, errmsg='用户不存在')

    # 3. 此时代表用户已存在,并查询该用户下发布的所有新闻
    news_list = None
    current_page = 1
    total_page = 1
    try:
        paginate = other.news_list.paginate(page,constants.USER_COLLECTION_MAX_NEWS,False)
        current_page = paginate.page
        total_page = paginate.pages
        news_list = paginate.items
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据查询失败')

    # 将模型列表 转换成 字典列表
    news_dict_li = []
    for news in news_list:
        news_dict_li.append(news.to_basic_dict())

    data = {
        'news_list':news_dict_li,
        'current_page':current_page,
        'total_page':total_page
    }

    return jsonify(errno=RET.OK, errmsg='ok',data=data)

@profile_blu.route('/other_info')
@user_login_data
def other_info():
    '''
    查询其他用户个人信息
    :return:
    '''
    # 1. 获取用户登录信息
    user = g.user

    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')

    # 2. 获取参数
    other_id = request.args.get('user_id')

    # 3.校验参数
    if not other_id:
        abort(404)

    # 4.查询个人信息
    try:
        other = User.query.get(other_id)
    except Exception as e:
        current_app.logger.error(e)

    # 5.校验用户是否存在
    if not other:
        abort(404)

    is_followed = False
    # if当前有作者 并且 登陆的用户已关注该作者
    if other and user:
        # 如果新闻的作者 在 用户关注的列表中
        if other in user.followed:
            is_followed = True

    # 6.此时用户已存在,返回结果

    data = {
        'is_followed':is_followed,
        'user':user.to_dict() if user else None,
        'other':other
    }

    return render_template('news/other.html',data=data)

@profile_blu.route('/user_follow')
@user_login_data
def user_follow():
    '''
    我的关注
    :return:
    '''
    # 1. 获取用户登录信息
    user = g.user

    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')

    # 2. 获取到传入参数(取到url后面的参数)
    page = request.args.get('page', 1)

    # 3. 判断参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    # 4. 查询参数 页数及每页个数()  返回一个Paginate对象，它包含指定范围内的结果
    followed_list = []
    current_page = 1
    total_page = 1
    try:
        paginate = user.followed.paginate(page, constants.USER_FOLLOWED_MAX_COUNT, False)

        current_page = paginate.page  # 当前页
        total_page = paginate.pages  # 总页数
        followed_list = paginate.items  # 当前页数据列表对象
    except Exception as e:
        current_app.logger.error(e)

    # 将当前页数据列表转换成字典对象
    users_dict_li = []

    for followed_user in followed_list:
        users_dict_li.append(followed_user.to_dict())

    data = {
        'current_page': current_page,
        'total_page': total_page,
        'users': users_dict_li
    }

    return render_template('news/user_follow.html',data=data)


@profile_blu.route('/news_list')
@user_login_data
def user_news_list():
    '''
    用户新闻列表
    :return:
    '''
    # 1. 获取用户登录信息
    user = g.user

    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')

    # 2. 获取到传入参数(取到url后面的参数)
    page = request.args.get('page', 1)

    # 3. 判断参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    # 4. 查询参数 页数及每页个数()  返回一个Paginate对象，它包含指定范围内的结果
    news_list = []
    current_page = 1
    total_page = 1
    try:
        paginate = News.query.filter(News.user_id == user.id).paginate(page, constants.USER_COLLECTION_MAX_NEWS,False)
        news_list = paginate.items # 当前页数据对象
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 将当前数据对象列表 遍历为字典对象列表
    news_dict_li = []
    for news in news_list:
        news_dict_li.append(news.to_review_dict())

    data = {
        'news_list':news_dict_li,
        'current_page':current_page,
        'total_page':total_page
    }

    return render_template('news/user_news_list.html',data=data)

@profile_blu.route('/news_release',methods=['GET','POST'])
@user_login_data
def news_release():
    '''
    用户发布新闻的逻辑
    :return:
    '''

    if request.method == 'GET':

        # 查询新闻分类
        try:
            categories = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)

        # 遍历新闻分类对象 加载新闻数据
        category_dict_li = []

        for category in categories:
            category_dict_li.append(category.to_dict())

        # 移除最新的分类
        category_dict_li.pop(0)

        data = {
            'categories':category_dict_li
        }

        return render_template('news/user_news_release.html',data = data)


    """
    发布新闻的逻辑
    1. 获取用户登录信息
    2. 获取参数(新闻标题,	新闻分类_id,	新闻摘要,索引图片,新闻内容)
    3. 判断参数
    4. 取到图片,将图片上传到七牛云
    5. 更新保存数据(初始化新闻模型)
    6. 保存到数据库
    7. 返回成功的结果
    """
    # 1. 获取用户登录信息
    user = g.user

    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')

    # 2. 获取参数(新闻标题, 新闻分类_id, 新闻摘要, 索引图片(文件), 新闻内容)
    title = request.form.get('title')
    category_id = request.form.get('category_id')
    digest = request.form.get('digest')
    index_image = request.files.get('index_image')
    content = request.form.get('content')
    # 新闻来源
    source = '星城哈哈'

    # 3. 判断参数
    if not all([title,category_id,digest,index_image,content]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    try:
        category_id = int(category_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 4.取到图片,将图片上传到七牛云
    try:
        index_image_data = index_image.read()
        # 上传到七牛云,返回一个key
        key = storage(index_image_data)
        print(key)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 5.更新保存数据(初始化新闻模型)
    news = News()
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + key
    news.content = content
    news.source = source
    # 当前新闻的作者id
    news.user_id = user.id
    # 当前新闻状态 如果为0代表审核通过，1代表审核中，-1代表审核不通过
    news.status = 1

    # 6.保存到数据库
    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据保存失败')

    # 7.返回成功的结果
    return jsonify(errno=RET.OK, errmsg='新闻发布成功')

@profile_blu.route('/collection')
@user_login_data
def user_collection():
    """
    收藏新闻的逻辑
    1. 获取用户登录信息
    2. 获取到传入参数
    3. 判断参数
    4. 查询参数
    5. 将查询的对象列表转换为字典对象
    6. 返回成功的结果
    :return:
   """
    # 1. 获取用户登录信息
    user = g.user

    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg='用户未登录')

    # 2. 获取到传入参数(取到url后面的参数)
    page = request.args.get('page',1)

    # 3. 判断参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    # 4. 查询参数 页数及每页个数()  返回一个Paginate对象，它包含指定范围内的结果
    news_list = []
    try:
        paginate = user.collection_news.paginate(page,constants.USER_COLLECTION_MAX_NEWS,False)

        current_page = paginate.page  # 当前页
        total_page = paginate.pages   # 总页数
        news_list = paginate.items    # 当前页数据列表对象
    except Exception as e:
        current_app.logger.error(e)

    # 将当前页数据列表转换成字典对象
    news_dict_li = []

    for news in news_list:
        news_dict_li.append(news.to_basic_dict())

    data = {
        'current_page':current_page,
        'total_page':total_page,
        'collections':news_dict_li
    }

    return render_template('news/user_collection.html',data=data)


@profile_blu.route('/pass_info',methods=['GET','POST'])
@user_login_data
def pass_info():
    """
    修改密码的逻辑
    1. 获取用户登录信息
    2. 获取到传入参数(旧密码,新密码)
    3. 判断参数
    4. 检查旧密码是否正确
    5. 更新并保存数据
    6. 返回成功的结果
    :return:
   """
    # 如果是get请求,加载数据
    if request.method == "GET":
        return render_template('news/user_pass_info.html')

    # 1. 获取用户登录信息
    user = g.user

    # 判断用户是否登陆
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登陆')

    # 2.获取到传入参数(旧密码,新密码)
    params_dict = request.json
    old_password = params_dict.get('old_password')
    new_password = params_dict.get('new_password')

    # 3.判断参数
    if not all([old_password,new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 4.检查旧密码是否正确
    if not user.check_password(old_password):
        return jsonify(errno=RET.PWDERR, errmsg='原密码不正确')

    # 5.更新并保存数据
    try:
        user.password = new_password
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='密码保存失败')

    # 6.返回成功的结果
    return jsonify(errno=RET.OK, errmsg='更新成功')


@profile_blu.route('/pic_info',methods=['GET','POST'])
@user_login_data
def pic_info():
    """
    头像上传的逻辑
    1. 获取用户登录信息
    2. 获取到传入参数(昵称,签名,性别)
    3. 判断参数
    4. 更新并保存数据
    5. 返回结果
    :return:
   """
    # 如果是get请求,加载数据
    if request.method == "GET":
        return render_template('news/user_pic_info.html', data={'user': g.user.to_dict()})

    # 1. 获取用户登录信息
    user = g.user

    # 判断用户是否登陆
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登陆')

    # 2. 获取到传入参数(头像对应的键)
    try:
        avatar = request.files.get('avatar').read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 3. 头像上传
    try:
        key = storage(avatar)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='头像上传错误')

    # 4.更新并保存数据(保存的是键 [图片url])
    user.avatar_url = key

    # try:
    #     db.session.commit()
    # except Exception as e:
    #     current_app.logger.error(e)
    #     return jsonify(errno=RET.DBERR, errmsg='数据保存错误')

    # 5.返回成功的结果
    return jsonify(errno=RET.OK, errmsg='更新成功',data = {'avatar_url' : constants.QINIU_DOMIN_PREFIX + key})


@profile_blu.route('/base_info',methods=['GET','POST'])
@user_login_data
def base_info():
    """
    个人资料逻辑处理
    1. 获取用户登录信息
    2. 获取到传入参数(昵称,签名,性别)
    3. 判断参数
    4. 更新并保存数据
    5. 返回结果
    :return:
   """
    # 如果是get请求,加载数据
    if request.method == "GET":
        return render_template('news/user_base_info.html', data={'user': g.user.to_dict()})

    # 1. 获取用户登录信息
    user = g.user

    # 判断用户是否登陆
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登陆')

    # 2. 获取到传入参数(昵称,签名,性别)
    params_dict = request.json
    nick_name = params_dict.get('nick_name')
    signature = params_dict.get('signature')
    gender = params_dict.get('gender')

    # 3.判断参数
    if not all([nick_name, signature, gender]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    if gender not in ('MAN', 'WOMAN'):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 4.更新并保存数据
    user.nick_name = nick_name
    user.signature = signature
    user.gender = gender
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据保存错误')

    # 更新个人名称
    session['nick_name'] = nick_name

    # 5.返回成功的结果
    return jsonify(errno=RET.OK, errmsg='更新成功')


@profile_blu.route('/info')
@user_login_data
def user_info():
    user = g.user

    if not user:
        # 代表没有登陆,重定向到首页
        return redirect('/')

    data = {
        'user': user.to_dict(),
    }
    return render_template('news/user.html',data=data)